package com.ckjw.gobang.jdbc;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.ckjw.gobang.connect.User;



/*** 
*
*数据库操作类
* @author  李传开 戴俊伟
* @Date    Jun 13, 2022
 */
public class DataBaseControl {

	/**
	 * 查询返回一条记录
	 * @param <T>
	 * @param clazz
	 * @param sql
	 * @param args
	 * @return
	 */
	public static <T> T getInstance(Class<T> clazz,String sql, Object... args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JDBCUtils.getConnection();

			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}

			rs = ps.executeQuery();
			// 获取结果集的元数据 :ResultSetMetaData
			ResultSetMetaData rsmd = rs.getMetaData();
			// 通过ResultSetMetaData获取结果集中的列数
			int columnCount = rsmd.getColumnCount();

			if (rs.next()) {
				T t = clazz.newInstance();
				// 处理结果集一行数据中的每一个列
				for (int i = 0; i < columnCount; i++) {
					// 获取列值
					Object columValue = rs.getObject(i + 1);

					// 获取每个列的列名
					// String columnName = rsmd.getColumnName(i + 1);
					String columnLabel = rsmd.getColumnLabel(i + 1);

					// 给t对象指定的columnName属性，赋值为columValue：通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columValue);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, ps, rs);

		}

		return null;
	}
   
	/**
	 * 针对于不同的表的通用的查询操作,返回多条记录
	 * @param <T> 对象类型
	 * @param clazz 类反射的字节文件
	 * @param sql sql查询命令
	 * @param args sql中？的内容逗号隔开
	 * @return
	 */
	public static <T> List<T> getForList(Class<T> clazz,String sql, Object... args){
		java.sql.Connection conn = null;
		java.sql.PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JDBCUtils.getConnection();

			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}

			rs = ps.executeQuery();
			// 获取结果集的元数据 :ResultSetMetaData
			java.sql.ResultSetMetaData rsmd = rs.getMetaData();
			// 通过ResultSetMetaData获取结果集中的列数
			int columnCount = rsmd.getColumnCount();
			//创建集合对象
			ArrayList<T> list = new ArrayList<T>();
			while (rs.next()) {
				T t = clazz.newInstance();
				// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
				for (int i = 0; i < columnCount; i++) {
					// 获取列值
					Object columValue = rs.getObject(i + 1);

					// 获取每个列的列名
					// String columnName = rsmd.getColumnName(i + 1);
					String columnLabel = rsmd.getColumnLabel(i + 1);

					// 给t对象指定的columnName属性，赋值为columValue：通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columValue);
				}
				list.add(t);
			}
			
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, ps, rs);

		}

		return null;
	}
		/**
		 * 通用的增删改操作
		 * @param sql 语句
		 * @param args  sql中？的内容，逗号隔开
		 */
		public static int  update(String sql,Object ...args){//sql中占位符的个数与可变形参的长度相同！
			Connection conn = null;
			PreparedStatement ps = null;
			int flag=0;
			try {
				//1.获取数据库的连接
				conn = JDBCUtils.getConnection();
				//2.预编译sql语句，返回PreparedStatement的实例
				ps = conn.prepareStatement(sql);
				//3.填充占位符
				for(int i = 0;i < args.length;i++){
					ps.setObject(i + 1, args[i]);//小心参数声明错误！！
				}
				//4.执行
				flag= ps.executeUpdate();
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				//5.资源的关闭
				JDBCUtils.closeResource(conn, ps);
				
			}
			
			return flag;
		}

	/**
	 * 增加用户
	 * @param id 
	 * @param name
	 * @param passwd
	 * @return 0 代表主键相同了
	 */
	public static boolean adduser(String id,String name, String passwd){
		User u=null;
		//查看主键是否已经存在
		//判断主键是否存在
		String sql1="select userid As userId,username As name,passwd from userinfo where userid=?";
		u=getInstance(User.class, sql1, id);
		if(u!=null)
		{
			System.out.println("id重复");
			return false;
		}
		String sql = "insert into userinfo(userid,username,passwd) value(?,?,?)";
		update(sql,id,name,passwd);
		return true;
	}
	/**
	 * 单个用户登录功能
	 * @param id
	 * @param passwd
	 * @return true 可以登录
	 * 小bug记录：getforlist返回的是列表，函数内为了可以加入对象，所以加了new list，所以不为空
	 * 所以也要关注返回结果是否为null类型
	 */
	public static boolean checkUser(String id,String passwd)
	{
		
		boolean flag=false;
		String sql= "select userid As userId,username As name,passwd from userinfo where userid=? and passwd=?";
		List<User> userlist= getForList(User.class,sql,id,passwd);
		if (userlist.size()!=0 )
		{
			flag=true;
		}
		return flag;
	}

	/**
	 * 获取所有在线用户成员信息
	 * @param usersid hm.keySet()
	 * @return 所有在线用户的数组
	 */
	public static ArrayList<User> getonlineuser(Set usersid)
	{
		ArrayList<User> list = new ArrayList<>();//存储所有在线用户
		if (usersid.size()!=0){
		Iterator<String> iterator = usersid.iterator();
		while (iterator.hasNext()) {
           
			String sql= "select userid As userId,username As name,passwd from userinfo where userid=?";
			User u=	getInstance(User.class,sql,iterator.next().toString());
			list.add(u);
        }
	}
		return list;
	}
}
